package com.ruoyi.partybuilding.controller;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import com.easy.query.core.basic.jdbc.tx.Transaction;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.partybuilding.common.*;
import com.ruoyi.partybuilding.common.EQuery.DeptInterceptor;
import com.ruoyi.partybuilding.domain.SysDeptRef;
import com.ruoyi.partybuilding.domain.SysUserRef;
import com.ruoyi.partybuilding.domain.vo.DeptOrgVo;
import com.ruoyi.partybuilding.domain.vo.UserMemberVo;
import com.ruoyi.partybuilding.service.impl.OrgServiceImpl;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
import javafx.util.Pair;
import lombok.var;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.partybuilding.domain.Org;
import com.ruoyi.common.core.page.TableDataInfo;
import io.swagger.annotations.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * 组织信息Controller
 * 
 * @author he-liangliang@outlook.com
 * @date 2024-11-27
 */
@Api(tags = "组织信息,部门扩展")
@RestController
@RequestMapping("/partybuilding/Org")
public class OrgController extends EQueryController<Org>
{

    @Autowired
    private ISysDeptService deptService;

    @Resource
    OrgServiceImpl orgService;
    /**
     * 查询组织信息列表
     */
    @ApiOperation("列表,查看有资源权限的组织")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:list')")
    @GetMapping("/list")
    @DataScope
    public TableDataInfoRows<DeptOrgVo> list(DeptOrgVo entity, PageSort pageRequest) {
        var re = orgService.deptVoList(entity, pageRequest);
        return toTableDataInfoRows(re);
    }
    @ApiOperation("查询部门，无权限过滤,返回的是所有,忽略分页size")
    @GetMapping("/orgList")
    public TableDataInfoRows<DeptOrgVo> orgList(DeptOrgVo entity, PageSort pageRequest) {
        pageRequest.setPageSize(Integer.MAX_VALUE);
        var re = orgService.deptVoList(entity, pageRequest);
        return toTableDataInfoRows(re);
    }

    @ApiOperation("包含部门信息-列表")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:list')")
    @GetMapping("/query")
    public R<Page<Org>> query(Org whereObj, PageDomain pageRequest) {
        var pData = queryHelper.queryable(Org.class).include(p->p.one(Org::getDept))
                .whereObject(whereObj !=null, whereObj)
                .toPageResult(pageRequest.getPageNum(), pageRequest.getPageSize());
        return R.ok(toPageData(pData));
    }
    @ApiOperation("包含部门信息-列表voList")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:list')")
    @GetMapping("/queryDeptVoList")
    public R<List<DeptOrgVo>> queryDeptVoList(DeptOrgVo entity) {
        return orgService.deptVoList(entity);
    }
    /**
     * 导出组织信息列表
     */
    @ApiOperation("导出")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:export')")
    @Log(title = "组织信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @DataScope
    public void export( DeptOrgVo org,PageDomain pageRequest,HttpServletResponse response) {
        var re = orgService.deptVoList(org);
        if (!R.isSuccess(re))
            return ;
        var list = re.getData();
        var util = new ExcelUtil<>(DeptOrgVo.class);
        util.exportExcel(response, list, "党员信息数据");
    }

    @ApiOperation("导入")
    @Log(title = "组织信息", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    @Transactional
    public R importData(MultipartFile file) throws Exception {

        var util = new ExcelUtil<DeptOrgVo>(DeptOrgVo.class);
        List<DeptOrgVo> orgVoList = util.importExcel(file.getInputStream());
        for (var item : orgVoList) {
            item.setParentId(100l);//固定为二级
            var dept=new SysDeptRef();
            BeanUtils.copyProperties(item,dept);
            dept.setCreateBy(getUsername());
            dept.setCreateTime(new Date());
            item.setDept(dept);
            var re=checkDeptOrg(item);
            if(re!=null)
                return re;
        }
        var depts=orgVoList.stream().map(p->p.getDept()).collect(Collectors.toList());
        queryHelper.query().insertable(depts).executeRows(true);
        orgVoList.forEach(p->p.setDeptId(p.getDept().getDeptId()));
       var orgList= orgVoList.stream().map(p-> DataUtil.copyProperties(p,new Org())).collect(Collectors.toList());
        queryHelper.query().insertable(orgList).executeRows();
        return R.ok();
    }

    @ApiOperation("导入模板下载")
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response)
    {
        var util = new ExcelUtil<>(DeptOrgVo.class);
        util.importTemplateExcel(response, "组织信息");
    }
    /**
     * 获取组织信息详细信息
     */
    @ApiOperation("详情")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:query')")
    @GetMapping(value = "/{id}")
    public R<Org> getInfo(@PathVariable("id") Long id)
    {
       return super.getInfo(id);
    }

    @ApiOperation("详情通过deptId")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:query')")
    @GetMapping(value = "getDeptVo/{deptId}")
    public R<DeptOrgVo> getDeptVo(@PathVariable("deptId") Long deptId) {
        var vo = new DeptOrgVo();
        vo.setDeptId(deptId);
        var re = queryDeptVoList(vo);

        if (R.isSuccess(re))
            if (!re.getData().isEmpty())
                return R.ok(re.getData().get(0));
            else return R.ok();
        else
            return (R) re;
    }


    /**
     * 新增组织信息
     */
    @ApiOperation("新增")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:add')")
    @Log(title = "组织信息", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @Transactional
    public R add(@RequestBody Org org) {
        //除重
        if (!StringUtils.isBlank(org.getNickName())) {
            var dept = queryHelper.query().queryable(SysDept.class)
                    .where(p -> p.or(() -> {
                        p.eq(SysDept::getDeptName, org.getNickName());
                    })).firstOrNull();
            if (dept != null)
                return R.fail("别称与名称有重复");
        }
        //创建部门
        return addDeptOrg(org);
    }
    public R checkDeptOrg(Org org){
        if (!StringUtils.isBlank(org.getNickName())) {
            var dept = queryHelper.query().queryable(SysDept.class)
                    .where(p -> p.or(() -> {
                        p.eq(SysDept::getDeptName, org.getNickName());
                    })).firstOrNull();
            if (dept != null)
                return R.fail("别称与名称有重复");
        }
        var dept=org.getDept();
        if(dept==null||StringUtils.isBlank(dept.getDeptName()))
            return R.fail("部门信息不能为空");
        if (!deptService.checkDeptNameUnique(dept))
        {
            return R.fail("新增部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        }
        dept.setDeptId(null);
        dept.setCreateBy(getUsername());
        dept.setCreateTime(new Date());
        org.setDeptName(dept.getDeptName());
        return null;
    }
    R<Integer>  addDeptOrg(Org org){
        var dept=org.getDept();

        if(dept==null)
            return R.fail("部门信息不能为空");
        dept.setDeptId(null);
        dept.setCreateBy(getUsername());
        dept.setCreateTime(new Date());
        if (!deptService.checkDeptNameUnique(dept))
        {
            return R.fail("新增部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        }
        var re=deptService.insertDept(dept);
        if(re!=1)
            return R.fail("新增失败："+re);
        var list=deptService.selectDeptList(dept);

        org.setDeptId(list.get(0).getDeptId());
        org.setDeptName(dept.getDeptName());
        var count=queryHelper.query().insertable(org).executeRows();
        if(count<1)
            return R.fail("新增失败："+count);
        return R.ok(1);
    }

    @Resource
    DeptInterceptor deptInterceptor;
    @ApiOperation(value = "部门列表，包含党员、班子统计信息",notes = "受资源权限控制,可以按部门deptId过滤，不传表示所有")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:query')")
    @GetMapping(value = "statList")
    public  R<List<DeptOrgVo>> statList(Long deptId) {
        var deptOrgVo = new DeptOrgVo();
        deptOrgVo.setDeptId(deptId);
        var re = orgService.deptInfoStat(deptOrgVo);
        var ids = deptInterceptor.scopeDeptIds(getLoginUser().getUser());
        if (ids != null) {
            var flist = re.getData().stream().filter(p -> ids.stream().anyMatch(x -> x.equals(p.getDeptId()))).collect(Collectors.toList());
            re.setData(flist);
        }
        return re;
    }
    /**
     * 修改组织信息
     */
    @ApiOperation("编辑")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:edit')")
    @Log(title = "组织信息", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @Transactional
    public R edit(@RequestBody DeptOrgVo org) {
        Long deptId = org.getDeptId();
        deptService.checkDeptDataScope(deptId);
        var dept = deptService.selectDeptById(deptId);
        dept.setDeptName(org.getDeptName());
        dept.setStatus(org.getStatus());
        dept.setOrderNum(org.getOrderNum());
        dept.setParentId(org.getParentId());
        if (!deptService.checkDeptNameUnique(dept)) {
            return R.fail("修改部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        } else if (dept.getParentId().equals(deptId)) {
            return R.fail("修改部门'" + dept.getDeptName() + "'失败，上级部门不能是自己");
        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) {
            return R.fail("该部门包含未停用的子部门！");
        }

        var oldOrg = queryHelper.queryable(Org.class).where(p -> p.eq(Org::getDeptId, deptId)).firstOrNull();
        Org newOrg = null;
        if (oldOrg == null) {
            newOrg = new Org();
            BeanUtils.copyProperties(org, newOrg);
            super.add(newOrg);
        } else if (Objects.equals(oldOrg.getId(), org.getId())) {
            newOrg = oldOrg;
            BeanUtils.copyProperties(org, newOrg);
            super.edit(newOrg);
        } else {
            throw new IllegalArgumentException("组织与部门信息不对应");
        }
        deptService.updateDept(dept);

        return R.ok();
    }
    /**
     * 修改组织信息
     */
    @ApiOperation("编辑指定属性，主要用于修改部门状态")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:edit')")
    @Log(title = "组织信息2", businessType = BusinessType.UPDATE)
    @PostMapping("/editDeptSet")
    public R editDeptSet(@RequestBody SysDept dept,List<String> fields){
          var re=  queryHelper.queryClient().updatable(dept).setColumns(p->{
                fields.forEach(p::column);
            }).whereColumns(p->p.column("id")).executeRows();
          if (re>0)
              return R.ok();
          return R.fail("更新失败");
    }
    /**
     * 删除组织信息
     */
    @ApiOperation("删除,通过deptId")
    @PreAuthorize("@ss.hasPermi('partybuilding:Org:remove')")
    @Log(title = "组织信息", businessType = BusinessType.DELETE)
	@PostMapping("remove/{ids}")
    public AjaxResult remove(@PathVariable Long deptId)
    {

        if (deptService.hasChildByDeptId(deptId))
        {
            return warn("存在下级部门,不允许删除");
        }
        if (deptService.checkDeptExistUser(deptId))
        {
            return warn("部门存在用户,不允许删除");
        }
        deptService.checkDeptDataScope(deptId);
        if(deptService.deleteDeptById(deptId)<1)
            return  error("删除失败");
        var re=queryHelper.query().deletable(Org.class).where(p->p.eq(Org::getDeptId,deptId)).disableLogicDelete().allowDeleteStatement(true).executeRows();
        if(re<1)
            logger.error("删除org失败，部门删除成功deptId:"+deptId);
        return success();
    }

    @Autowired
    private ISysDictDataService dictDataService;

    @Autowired
    private ISysDictTypeService dictTypeService;

    @Transactional
    @PostMapping("Init")
    public  R Init() {

        var strDicts=DictPB.strDictOut();
        return addDicts(strDicts);
        //
//        var dicts = DictPB.outDict();
//
//        return addDicts(dicts);
    }

    private R<Object> addDicts(Pair<SysDictType, SysDictData[]>[] dicts) {
        for (var item : dicts) {
            if (!dictTypeService.checkDictTypeUnique(item.getKey()))
                return R.fail("重复的字典类型：" + item.getKey().getDictType());
            item.getKey().setCreateBy(getUsername());
            dictTypeService.insertDictType(item.getKey());

            for (SysDictData dictData : item.getValue()) {
                dictData.setDictType(item.getKey().getDictType());
                dictData.setCreateBy(getUsername());
                dictDataService.insertDictData(dictData);
            }
        }
        return R.ok();
    }

}
